package com.javacoo.xservice.base.utils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.javacoo.xservice.base.support.cache.CacheFunction;
import com.javacoo.xservice.base.support.cache.CacheHolder;
import com.javacoo.xservice.base.support.cache.CacheManager;

import lombok.extern.slf4j.Slf4j;

/**
 * redis工具类
 * <li></li>
 * @author duanyong@jccfc.com
 * @date 2020/10/14 9:37
 */
@Slf4j
@Component
public class CacheUtil {
    /**
     * 设置单个值
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, Object value) {
        return getCacheManager() == null ? false : getCacheManager().set(key,value);
    }

    /**
     * 设置单个值并设置失效时间
     * @param key
     * @param value
     * @param expireTime 缓存时间，单位秒
     * @return
     */
    public boolean setAndExpire(String key, Object value, int expireTime) {
        return getCacheManager() == null ? false : getCacheManager().setAndExpire(key,value,expireTime);
    }

    /**
     * 获取单个值
     * @param key
     * @return
     */
    public <T> T get(String key) {
        return getCacheManager() == null ? null : getCacheManager().get(key);
    }

    /**
     * 批量设置hash
     * @param key
     * @param hash
     * @return
     */
    public boolean hmSet(String key, Map<String, Object> hash) {
        return getCacheManager() == null ? false : getCacheManager().hmSet(key,hash);
    }

    /**
     * 给hash字段设置值
     * @param key
     * @param field
     * @param value
     * @return
     */
    public boolean hSet(String key, String field, Object value) {
        return getCacheManager() == null ? false : getCacheManager().hSet(key,field,value);
    }

    /**
     * 获取hash值
     *  引用见{@link RedisTemplate}
     * @param key
     * @param field
     * @return
     */
    public <T> T hGet(String key, String field) {
        return getCacheManager() == null ? null : getCacheManager().hGet(key,field);
    }

    /**
     * 如果缓存key不存在则设置缓存并设置失效时间，否则不做操作
     * @param key
     * @param value
     * @param time 缓存时间，单位秒
     * @return
     */
    public boolean setIfAbsent(final String key, Object value, int time) {
        return getCacheManager() == null ? false : getCacheManager().setIfAbsent(key,value,time);
    }

    /**
     * 删除缓存
     * @param key
     * @return
     */
    public boolean del(String key) {
        return getCacheManager() == null ? false : getCacheManager().del(key);
    }

    /**
     * 删除hash缓存
     * @param key
     * @param fields
     * @return
     */
    public long hashDel(String key, String... fields) {
        return getCacheManager() == null ? -1 : getCacheManager().hashDel(key,fields);
    }

    /**
     * redis 自增
     * @param key
     * @param liveTime 天数 这个计数器的有效存留时间
     * @param delta 自增量
     * @return
     */
    public long incr(String key, long liveTime, long delta) {
        return getCacheManager() == null ? -1 : getCacheManager().incr(key,liveTime,delta);
    }

    /**
     * 获取缓存
     * <p>
     * 说明:Function版
     * </p>
     * @author DuanYong
     * @param key 缓存KEY
     * @param expireTime 超时时间，单位 秒
     * @param clazz 目标对象类型
     * @param function 执行函数
     * @param p 附加给function的参数
     * @return 目标对象
     */
    public <T,P> T getCacheValueFunction(String key,int expireTime, Class<T> clazz, Function<P,T> function,P p) {
        return getCacheFunction() == null ? null : getCacheFunction().getCacheValueFunction(key,expireTime,clazz,function,p).orElse(null);
    }
    /**
     * 获取缓存
     * <p>
     * 说明:Supplier版
     * </p>
     * @author DuanYong
     * @param key 缓存KEY
     * @param clazz 目标对象类型
     * @param function 执行函数
     * @return 目标对象
     */
    public <T> T getCacheValueFunction(String key,int expireTime, Class<T> clazz, Supplier<T> function) {
        return getCacheFunction() == null ? null : getCacheFunction().getCacheValueFunction(key,expireTime,clazz,function).orElse(null);
    }
    /**
     * 获取集合缓存
     * <p>说明:Function版本</p>
     * @author DuanYong
     * @param key 缓存KEY
     * @param clazz 目标对象类型
     * @param function 执行函数
     * @param p 附加给function的参数
     * @return 目标对象
     */
    public <P,T> List<T> getCacheListValueFunction(String key,int expireTime, Class<T> clazz, Function<P,List<T>> function,P p) {
        return getCacheFunction() == null ? Collections.emptyList() : getCacheFunction().getCacheListValueFunction(key,expireTime,clazz,function,p).orElse(Collections.emptyList());
    }
    /**
     * 获取集合缓存
     * <p>说明:Supplier版本</p>
     * @author DuanYong
     * @param key 缓存KEY
     * @param clazz 目标对象类型
     * @param function 执行函数
     * @return 目标对象
     */
    public <T> List<T> getCacheListValueFunction(String key,int expireTime, Class<T> clazz,Supplier<List<T>> function) {
        return getCacheFunction() == null ? Collections.emptyList() : getCacheFunction().getCacheListValueFunction(key,expireTime,clazz,function).orElse(Collections.emptyList());
    }
    /**
     * 获取缓存管理器
     * <li></li>
     * @author duanyong@jccfc.com
     * @return: com.javacoo.xservice.base.support.cache.CacheManager
     */
    private CacheManager getCacheManager(){
        if(!CacheHolder.getCacheManager().isPresent()){
            log.error("不支持缓存");
            return null;
        }
        return CacheHolder.getCacheManager().get();
    }
    /**
     * 获取缓存函数接口
     * <li></li>
     * @author duanyong@jccfc.com
     * @return: com.javacoo.xservice.base.support.cache.CacheFunction
     */
    private CacheFunction getCacheFunction(){
        if(!CacheHolder.getCacheManager().isPresent()){
            log.error("不支持缓存");
            return null;
        }
        if(!CacheHolder.getCacheFunction().isPresent()){
            log.error("不支持缓存函数");
            return null;
        }
        return CacheHolder.getCacheFunction().get();
    }
}
